﻿package shooter 
{
	import com.greensock.TweenNano;
	import exey.utils.MathUtils;
	import flash.geom.Matrix3D;
	import flash.geom.Vector3D;
	import render3d.interfaces.IRender3DAdapter;
	
	/**
	 * Monster spawn, movement, destroying, killing a hero
	 * @author Exey Panteleev
	 */
	public class MonstersController 
	{
		private const MONSTER_SPEED:Number = 3;  // pixels per tick
		private const MONSTER_SPEED_MULTIPLIER:Number = 0.12; // increasing speed with game score
		private const MIN_RESPAWN_DELAY:Number = 0.5; // seconds
		private const MAX_RESPAWN_DELAY:Number = 2; // seconds
		private const KILL_HERO_DISTANCE:Number = 4; // pixels
		private const MIN_RESPAWN_MONSTERS:Number = 1; // quantity
		private const MAX_RESPAWN_MONSTERS:Number = 2; // quantity
		
		private var _monsters:Object = { };
		private var _monsterRespawnsData:Array;
		private var _monsterIndex:int;
		
		private var game:Game;
		private var render:IRender3DAdapter;
		
		public function MonstersController(game:Game, monsterRespawnsData:Array) 
		{
			this.game = game;
			this.render = game.render
			_monsterRespawnsData = monsterRespawnsData;
		}

		public function respawnMonsters():void 
		{
			if (!game.isAlive) return;
			var quantity:uint = MathUtils.randRange(MIN_RESPAWN_MONSTERS, MAX_RESPAWN_MONSTERS);			
			var newMonsterPositions:Object = { }
			// Randomize monsters respawn positions
			for (var k:int = 0; k < _monsterRespawnsData.length; k++) 
			{
				for (var i:int = 0; i < quantity; i++) 
				{
					newMonsterPositions[_monsterIndex] = new Vector3D(_monsterRespawnsData[k].x, _monsterRespawnsData[k].y, 107)
					_monsterIndex++;
				}
			}
			addMonsters(newMonsterPositions);
			// call next respawn
			TweenNano.delayedCall(MathUtils.randRange(MIN_RESPAWN_DELAY, MAX_RESPAWN_DELAY), respawnMonsters)
		}
		
		public function addMonsters(newMonsterPositions:Object):void 
		{
			for (var monsterId:String in newMonsterPositions) 
			{				
				var monsterPosition:Vector3D = newMonsterPositions[monsterId]
				var monster:Monster = new Monster(game.render, monsterId);
				monster.setPosition(monsterPosition.x + MathUtils.randRange( -game.level.tileSize, game.level.tileSize ), 
									monsterPosition.y + MathUtils.randRange( -game.level.tileSize, game.level.tileSize ), 
									monsterPosition.z)
				_monsters[monsterId] = monster;
				render.addChild(monster);
				//render.addChild(monster);
				//trace("  ", monsterId, monsterPosition.x, monsterPosition.y)
			}
		}
		
		public function update():void 
		{
			var speed:Number = MONSTER_SPEED+MONSTER_SPEED*game.score*MONSTER_SPEED_MULTIPLIER;
			var cameraMatrix:Matrix3D = game.render.getCameraTransformation();
			
			for (var monsterId:String in _monsters) 
			{
				var monster:Monster = _monsters[monsterId]
				var dx:Number = cameraMatrix.position.x - monster.getPosition().x;
				var dy:Number = cameraMatrix.position.y - monster.getPosition().y;
				var dist:Number = Math.sqrt(dy*dy +  dx*dx)
				
				// check is Monster hit Hero
				if (dist < KILL_HERO_DISTANCE) 
				{
					// hero is killed by monster
					game.isAlive = false;
					game.gameOver();
				} 
				else 
				{
					// follow monster to hero
					var radian:Number = Math.atan2(dy, dx);				
					monster.appendTranslation(Math.cos(radian) * speed, Math.sin(radian) * speed, 0)
				}
			}
		}
		
		/** clean up the level **/
		public function destroyAllMonsters():void 
		{
			if (_monsters) 
			{
				for (var monsterId:String in _monsters) 
				{
					if (_monsters[monsterId]) 
						_monsters[monsterId].destroy();
					delete _monsters[monsterId];
				}
			}
			_monsters = { };
			_monsterIndex = 0;
		}
		
		public function get monsters():Object { return _monsters; }
	}
}